package com.seleniti.enpareja.web.desktop.client.control.activity;

import org.ioc.commons.flowcontrol.logincontroller.IsLoggedUserInfoConsumer;
import org.ioc.commons.flowcontrol.logincontroller.LoginController;
import com.seleniti.enpareja.controller.control.controller.LoginFailedCause;
import org.ioc.commons.flowcontrol.placecontroller.HasPlaceData;
import org.ioc.commons.flowcontrol.placecontroller.PlaceController;
import org.ioc.commons.impl.gwt.client.flowcontrol.activitymapper.AppActivity;
import org.ioc.commons.model.globaldata.GlobalDataController;
import org.ioc.commons.ui.IsWidget;
import org.ioc.commons.utils.FormatterLogger;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Widget;
import com.seleniti.enpareja.controller.common.GlobalData;
import com.seleniti.enpareja.controller.common.domain.LoggedUserInfo;
import com.seleniti.enpareja.controller.control.controller.LoginParams;
import com.seleniti.enpareja.controller.control.factory.ClientFactory;
import com.seleniti.enpareja.controller.control.place.EnParejaPlace;
import com.seleniti.enpareja.controller.model.integration.service.SecurityManagementService;

/**
 * A generic activity for all the views on the application.
 * 
 * If someone needs some special functionallity other activities can inherit
 * from it.
 * 
 * @author Jesús Lunar Pérez
 * 
 */
public class DesktopGenericActivity<V extends IsWidget> extends AbstractActivity implements AppActivity<V>,
		IsLoggedUserInfoConsumer<LoggedUserInfo> {

	private static final FormatterLogger logger = FormatterLogger.getLogger(DesktopGenericActivity.class);

	private static boolean updatedLastAccess;

	private V view;
	private final boolean requiresBeLoggedIn;
	private GlobalDataController<GlobalData> globalDataController;
	private PlaceController placeController;
	private SubPlaceTokenHandler<V> subPlaceTokenHandler;
	private AcceptsOneWidget panel;
	private boolean initialized;

	private SecurityManagementService securityService;

	private LoginController<LoggedUserInfo, LoginFailedCause, LoginParams, String> loginController;

	public DesktopGenericActivity(V view, boolean requiresBeLoggedIn) {
		setView(view);
		this.requiresBeLoggedIn = requiresBeLoggedIn;
	}

	public DesktopGenericActivity(V view, boolean requiresBeLoggedIn, SubPlaceTokenHandler<V> subPlaceTokenHandler) {
		this(view, requiresBeLoggedIn);
		setSubPlaceTokenHandler(subPlaceTokenHandler);
	}

	@Override
	public void start(AcceptsOneWidget panel, EventBus eventBus) {

		assert (this.initialized) : "The activity has to be initialized";

		this.panel = panel;

		if (this.requiresBeLoggedIn) {
			this.loginController.requiresLoggedUserInfo(this);
		} else {
			continueStart();
		}

	}

	@Override
	public void onLoggedUserInfoNotReadyYet() {
		/*
		 * Nothing to do
		 */
	}

	@Override
	public void onLoggedUserInfoDataUpdated(LoggedUserInfo loggedUserInfo) {
		// Nothing to do
	}

	@Override
	public void onLoggedUserInfoDataReady() {
		logger.entering("onRequiredGlobalDataReady");

		LoggedUserInfo loggedUserInfo = this.loginController.getLoggedUserInfo();
		
		logger.info("Logged user info {0}", loggedUserInfo);
		
		if (loggedUserInfo == null || !loggedUserInfo.isLogged()) {
			HasPlaceData currentPlaceData = this.placeController.getCurrentPlaceData();
			EnParejaPlace goWhenLoginOk = (EnParejaPlace) (currentPlaceData != null ? currentPlaceData.getPlaceId() : null);

			logger.info("Not logged in" );
			
//			if(loggedUserInfo.isRequiredExternalLoginUrl()) {
//				logger.info("Required external login url");
//				this.securityService.getExternalLogin(this.placeController.currentPlaceAsUrl()).to(new ReceiverAdapter<String>() {
//
//					@Override
//					public void success(String externalLoginUrl) {
//						placeController.goTo(EnParejaPlace.ExternalLoginPlace, false, null, externalLoginUrl);
//					}
//				});
//			} else {
				logger.info("Going to login place");
				this.placeController.goTo(EnParejaPlace.LoginPlace, false, null, goWhenLoginOk);
//			}
			return;
		} else {
			logger.info("Logged in: {0}", loggedUserInfo);
			if(!DesktopGenericActivity.updatedLastAccess) {
				logger.info("Updating last access date");
				DesktopGenericActivity.updatedLastAccess = true;
				this.securityService.updateLastAccess(loggedUserInfo.getUserId()).caller(this);
			}
		}

		continueStart();
		logger.exiting("onRequiredGlobalDataReady");
	}

	protected void continueStart() {
		panel.setWidget((Widget) view.asWidget());
	}

	public void setClientFactory(ClientFactory clientFactory) {
		this.initialized = true;
		this.globalDataController = clientFactory.getGlobalDataController();
		this.placeController = clientFactory.getPlaceController().forThisObject(this);
		this.loginController = clientFactory.getLoginController();

		this.securityService = clientFactory.getServiceManager().serviceFactory().securityManagementService();
	}

	private void setView(V view) {
		this.view = view;
	}

	@Override
	public V getView() {
		return view;
	}

	@Override
	public void setSubPlaceToken(String subPlaceToken) {
		if (this.subPlaceTokenHandler != null && subPlaceToken != null && !subPlaceToken.isEmpty()) {
			this.subPlaceTokenHandler.handleSubPlaceToken(this.view, subPlaceToken);
		}
	}

	@Override
	public void setSubPlaceTokenHandler(SubPlaceTokenHandler<V> subPlaceTokenHandler) {
		this.subPlaceTokenHandler = subPlaceTokenHandler;
	}

	@Override
	public String mayStop() {
		return super.mayStop();
	}
}
